package org.elwiki.editor;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
//:FVK:import org.elwiki.storage.IModel;
import org.elwiki_data.PagesStore;
import org.elwiki_data.WikiPage;

import erwiki.api.pages.PageManager;

/**
 * Dialog for prepare and construct simple page link.</br>
 * Link format, for example: [ page name | @7263 ].
 *
 * @author vfedorov
 */
public class PageLinkDialog extends Dialog {
	private static final long serialVersionUID = -932922830755026631L;

	class ViewContentProvider implements IStructuredContentProvider, ITreeContentProvider {
		private static final long serialVersionUID = -8389133578293411677L;

		@Override
		public void inputChanged(Viewer v, Object oldInput, Object newInput) {
		}

		@Override
		public void dispose() {
		}

		@Override
		public Object[] getElements(Object parent) {
			Object[] result;
			if (parent instanceof WikiPage) {
				WikiPage wikiPage = (WikiPage) parent;
				result = wikiPage.getChildren().toArray();
			} else if (parent instanceof PagesStore) {
				PagesStore pagesStore = (PagesStore) parent;
				result = pagesStore.getWikipages().toArray();
			} else {
				result = new Object[0];
				Assert.isTrue(false, ":FVK: Internal error.");
			}
			return result;
		}

		@Override
		public Object getParent(Object child) {
			if (child instanceof WikiPage) {
				return ((WikiPage) child).getParent();
			}
			return null;
		}

		@Override
		public Object[] getChildren(Object parent) {
			if (parent instanceof WikiPage) {
				return ((WikiPage) parent).getChildren().toArray();
			}
			return new Object[0];
		}

		@Override
		public boolean hasChildren(Object parent) {
			if (parent instanceof WikiPage) {
				return ((WikiPage) parent).getChildren().size() > 0;
			}
			return false;
		}
	}

	class ViewLabelProvider extends LabelProvider {
		private static final long serialVersionUID = -3239630456603888576L;

		@Override
		public String getText(Object obj) {
			String result;
			if (obj instanceof WikiPage) {
				WikiPage wikiPage = (WikiPage) obj;
				result = wikiPage.getName();
			} else {
				result = obj.toString();
			}
			return result;
		}

		/*:FVK: - старое, для rap.ui.workbench:
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
		@Override
		public Image getImage(Object obj) {
			String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
			if (obj instanceof WikiPage) {
				imageKey = ISharedImages.IMG_OBJ_FOLDER;
			}
			return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey);
		}
		 */
	}

	class PagesViewerFilter extends ViewerFilter {
		private static final long serialVersionUID = 5881635560303210175L;

		@Override
		public boolean select(Viewer viewer, Object parent, Object element) {
			if (element instanceof WikiPage) {
				WikiPage wikiPage = (WikiPage) element;
				String pageNamePattern = PageLinkDialog.this.textPageNamePattern.getText().toLowerCase();
				return checkPageName(wikiPage, pageNamePattern);
			}
			return false;
		}

		/**
		 * Recursion code.
		 * 
		 * @param wikiPage
		 * @param pageNamePattern
		 *            This string must be lower case.
		 * @return
		 */
		boolean checkPageName(WikiPage wikiPage, String pageNamePattern) {
			String pageName = wikiPage.getName().toLowerCase();
			if (pageName.indexOf(pageNamePattern) >= 0) {
				return true;
			}
			for (WikiPage childrenPage : wikiPage.getChildren()) {
				if (checkPageName(childrenPage, pageNamePattern)) {
					return true;
				}
			}
			return false;
		}
	}

	private Text textLinkText;
	private Text textPageNamePattern;
	private Text textPageId;

	private String linkText;

	private String pageId;
	private TreeViewer treeViewer;

	final PageManager pageManager;
	private boolean isTextExists = false;

	/**
	 * Create the dialog.
	 * 
	 * @param parentShell
	 */
	public PageLinkDialog(Shell parentShell, PageManager pageManager) {
		super(parentShell);
		this.pageManager = pageManager;
	}

	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Ссылка страницы");
	}

	/**
	 * Create contents of the button bar.
	 * 
	 * @param parent
	 */
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		createButton(parent, IDialogConstants.OK_ID, "Вввод", true);
		createButton(parent, IDialogConstants.CANCEL_ID, "Отмена", false);
	}

	/**
	 * Return the initial size of the dialog.
	 */
	@Override
	protected Point getInitialSize() {
		return new Point(640, 720);
	}

	/**
	 * Create contents of the dialog.
	 * 
	 * @param parent
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		Composite container = (Composite) super.createDialogArea(parent);
		container.setLayout(new GridLayout(2, false));

		Label lblLinkText = new Label(container, SWT.NONE);
		lblLinkText.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblLinkText.setText("Текст ссылки:");

		this.textLinkText = new Text(container, SWT.BORDER);
		this.textLinkText.setText("");
		this.textLinkText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

		Group group = new Group(container, SWT.NONE);
		group.setLayout(new GridLayout(2, false));
		group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
		group.setText("Страница");

		Label lblPageId = new Label(group, SWT.NONE);
		lblPageId.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblPageId.setText("Идентификатор:");

		this.textPageId = new Text(group, SWT.BORDER);
		this.textPageId.setEnabled(false);
		this.textPageId.setEditable(false);
		GridData gd_textPageId = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1);
		gd_textPageId.widthHint = 160;
		this.textPageId.setLayoutData(gd_textPageId);

		Label lblPageName = new Label(group, SWT.NONE);
		lblPageName.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblPageName.setText("Шаблон имени:");

		this.textPageNamePattern = new Text(group, SWT.BORDER);
		GridData gd_textPageNamePattern = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
		gd_textPageNamePattern.widthHint = 190;
		this.textPageNamePattern.setLayoutData(gd_textPageNamePattern);
		this.textPageNamePattern.addModifyListener(new ModifyListener() {
			private static final long serialVersionUID = 4726490109735844536L;

			public void modifyText(ModifyEvent arg0) {
				PageLinkDialog.this.treeViewer.refresh();
				PageLinkDialog.this.treeViewer.expandAll();
			}
		});

		// -- tree viewer -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
		this.treeViewer = new TreeViewer(group, SWT.BORDER);
		Tree tree = this.treeViewer.getTree();
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
		this.treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				treeSelectionChanged((IStructuredSelection) event.getSelection());
			}
		});
		this.treeViewer.setContentProvider(new ViewContentProvider());
		this.treeViewer.setLabelProvider(new ViewLabelProvider());
		this.treeViewer.setSorter(new ViewerSorter() {
			private static final long serialVersionUID = 8907584367998250840L;

			@Override
			public int compare(Viewer viewer1, Object e1, Object e2) {
				if (e1 instanceof WikiPage && e2 instanceof WikiPage) {
					String s1 = ((WikiPage) e1).getName();
					String s2 = ((WikiPage) e2).getName();
					return s1.compareTo(s2);
				}
				return super.compare(viewer1, e1, e2);
			}

		});
		this.treeViewer.addFilter(new PagesViewerFilter());

//:FVK:		PagesStore pages = IModel.INSTANCE.getPagesStore(); // workaround.
//		this.treeViewer.setInput(pages);

		this.treeViewer.expandToLevel(2);

		return container;
	}

	protected void treeSelectionChanged(IStructuredSelection selection) {
		if (!selection.isEmpty()) {
			Object selObj = selection.getFirstElement();
			WikiPage wikiPage = (WikiPage) selObj;

			String cdoId = wikiPage.getId();//:FVK: this.pageManager.getPageId(wikiPage);
			this.textPageId.setText(cdoId);
			if (!this.isTextExists) {
				this.textLinkText.setText(wikiPage.getName());
			}
		}
	}

	@Override
	protected void okPressed() {
		this.linkText = this.textLinkText.getText();
		this.pageId = this.textPageId.getText();
		super.okPressed();
	}

	public void setLinkText(String selection) {
		if (selection.trim().length() != 0) {
			this.isTextExists = true;
		}
		this.textLinkText.setText(selection);
	}

	public String getLinkText() {
		return this.linkText;
	}

	public String getPageId() {
		return this.pageId;
	}

}
